package 行为型模式.模板方法模式;

/**
 * 主要组成部分
 * 抽象类(Abstract Class)
 * 定义抽象的原语操作(primitive operations)，具体的子类将重定义它们以实现一个算法的各步骤
 * 实现一个模板方法，定义一个算法的骨架。该模板方法不仅调用原语操作，也调用定义在抽象类或其他对象中的操作
 * 具体类(Concrete Class)
 * 实现原语操作以完成算法中与特定子类相关的步骤
 */

abstract class Beverage {
	// 模板方法 - 定义制作饮料的步骤（算法骨架）
	public final void prepareBeverage() {
		boilWater();
		brew();
		pourInCup();
		if (customerWantsCondiments()) {
			addCondiments();
		}
	}

	// 具体步骤 - 烧水（共用方法）
	private void boilWater() {
		System.out.println("烧开水");
	}

	// 具体步骤 - 倒入杯子（共用方法）
	private void pourInCup() {
		System.out.println("倒入杯子");
	}

	// 抽象方法 - 冲泡（由子类实现）
	protected abstract void brew();

	// 抽象方法 - 添加调料（由子类实现）
	protected abstract void addCondiments();

	// 钩子方法 - 顾客是否要加调料（默认返回true，子类可覆盖）
	protected boolean customerWantsCondiments() {
		return true;
	}
}
class Tea extends Beverage {
	@Override
	protected void brew() {
		System.out.println("用沸水浸泡茶叶");
	}

	@Override
	protected void addCondiments() {
		System.out.println("加柠檬");
	}

	// 覆盖钩子方法 - 询问顾客是否要加柠檬
	@Override
	protected boolean customerWantsCondiments() {
		String answer = getUserInput();
		return answer.toLowerCase().startsWith("y");
	}

	private String getUserInput() {
		// 实际应用中可以从控制台获取用户输入
		// 这里简化为固定返回"yes"
		return "yes";
	}
}
class Coffee extends Beverage {
	@Override
	protected void brew() {
		System.out.println("用沸水冲泡咖啡粉");
	}

	@Override
	protected void addCondiments() {
		System.out.println("加糖和牛奶");
	}
}

public class TemplateMethod 
{
	public static void main(String[] args) 
	{
		System.out.println("制作茶...");
		Beverage tea = new Tea();
		tea.prepareBeverage();

		System.out.println("\n制作咖啡...");
		Beverage coffee = new Coffee();
		coffee.prepareBeverage();
	}
}
